"""
五、按要求操作

1. 定义一个类Student，用来存放学生的信息
2. 定义一个类Wrapper，用来包装学生的信息，学生信息以Student的实例的形式存放在Wrapper内部
3. 使用时，直接实例化Wrapper，不直接实例化Student，实例化Student的工作在Wrapper内部做；
   可以以关键字的形式提供属性的名字和值，也可以不提供任何属性
   Student实例对象存放在Wrapper实例中，名字是 self.data
4. 获取实例的 name, age, gender 等属性时，返回self.data里面对应名字的值
5. 设置实例的 name, age, gender 等属性时，对应地设置self.data里面对应的key
6. 删除实例的 name, age, gender 等属性时，对应地删除self.data里面对应的key
"""

class Student:

    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)


class Wrapper:

    """
    用来包装Student的类，把对Wrapper的getattr, setattr,
    delattr的操作重定向/调度到里面的Student对象上。
    """

    def __init__(self, **kwargs):
        # 这里把Student实例保存到self.data时，必须使用内置字典对象 self.__dict__，
        # 不能使用obj.data = Student(**kwargs) 这样的形式，
        # 以免触发 __getattr__ 函数。
        # 因为此时 self.data 还不存在，如果此时触发 __getattr__ 函数，
        # 就会造成无限的递归。
        self.__dict__['data'] = Student(**kwargs)

    def __getattr__(self, name):
        return getattr(self.data, name)

    def __setattr__(self, name, value):
        return setattr(self.data, name, value)

    def __delattr__(self, name):
        return delattr(self.data, name)


if __name__ == '__main__':
    obj = Wrapper(name='Alice', age=18, phone='18612345678')
    obj.addr = 'Shenzhen, Guangdong, China'
    print(obj.name, obj.age)
    print(getattr(obj, 'phone', 'not available'))
    del obj.phone
    # delattr(obj, 'phone')
    print(getattr(obj, 'phone', 'not available'))
